﻿using System;
using System.IO;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;

using FarseerPhysics.Collision;
using FarseerPhysics.Common;
using Microsoft.Xna.Framework.GamerServices;
using System.Xml.Serialization;

namespace Spacer {
	public class SolarSys : Activity {
		public SolarSys() {
			// Retrieve content
            Backdrop = Main.FindTexture("StarField");
            ItemsMenu = Main.FindTexture("ItemsMenu");
            MiniMap = Main.FindTexture("MiniMap");
            Fuel = Main.FindTexture("Fuel");
            Circle = Main.FindTexture("SmallCircle");

			// Force some settings
			FarseerPhysics.Settings.AllowSleep = true;

			#if XBOX360 // Way too much of a performance hit!
			FarseerPhysics.Settings.PositionIterations = 8;
			FarseerPhysics.Settings.VelocityIterations = 12;
			FarseerPhysics.Settings.ContinuousPhysics = false;
			#else
			FarseerPhysics.Settings.PositionIterations = 15;
			FarseerPhysics.Settings.VelocityIterations = 25;
			#endif

			// Create our instance
			Instance = new FarseerPhysics.Dynamics.World( new Vector2(0f,0f) );
			Instance.AutoClearForces = true;
			Instance.EnableSubStepping = true;
			Instance.Enabled = true;

			// Create our lists
			Drawables = new HashSet<Drawable>();
			Entities = new Dictionary<Guid,Entity>();
			AddedDrawables = new HashSet<Drawable>();
			AddedEntities = new Dictionary<Guid,Entity>();
			RemovedDrawables = new HashSet<Drawable>();
			RemovedEntities = new Dictionary<Guid,Entity>();
			NextAvailableEntID = 0;

			// Debug rendering
			View = new FarseerPhysics.DebugViews.DebugViewXNA( Instance );
			View.LoadContent( Globals.GameInstance.GraphicsDevice, Globals.GameInstance.Content );
			View.Flags |= FarseerPhysics.DebugViewFlags.CenterOfMass;
			View.Flags |= FarseerPhysics.DebugViewFlags.ContactPoints;
			View.Flags |= FarseerPhysics.DebugViewFlags.PerformanceGraph;
			HideObjects = false;
		}

		public SolarSys( Galaxy galaxy, Type generator ) {
			Galaxy = galaxy;
			GeneratorType = generator;
			GeneratorTypeName = GeneratorType.FullName;

			// Retrieve content
            Backdrop = Main.FindTexture("StarField");
            ItemsMenu = Main.FindTexture("ItemsMenu");
            MiniMap = Main.FindTexture("MiniMap");
            Fuel = Main.FindTexture("Fuel");
            Circle = Main.FindTexture("SmallCircle");

			// Force some settings
			FarseerPhysics.Settings.AllowSleep = true;

			#if XBOX360 // Way too much of a performance hit!
			FarseerPhysics.Settings.PositionIterations = 8;
			FarseerPhysics.Settings.VelocityIterations = 12;
			FarseerPhysics.Settings.ContinuousPhysics = false;
			#else
			FarseerPhysics.Settings.PositionIterations = 15;
			FarseerPhysics.Settings.VelocityIterations = 25;
			#endif

			// Create our instance
			Instance = new FarseerPhysics.Dynamics.World( new Vector2(0f,0f) );
			Instance.AutoClearForces = true;
			Instance.EnableSubStepping = true;
			Instance.Enabled = true;

			// Create our lists
			Drawables = new HashSet<Drawable>();
			Entities = new Dictionary<Guid,Entity>();
			AddedDrawables = new HashSet<Drawable>();
			AddedEntities = new Dictionary<Guid,Entity>();
			RemovedDrawables = new HashSet<Drawable>();
			RemovedEntities = new Dictionary<Guid,Entity>();
			NextAvailableEntID = 0;

			// Debug rendering
			View = new FarseerPhysics.DebugViews.DebugViewXNA( Instance );
			View.LoadContent( Globals.GameInstance.GraphicsDevice, Globals.GameInstance.Content );
			View.Flags |= FarseerPhysics.DebugViewFlags.CenterOfMass;
			View.Flags |= FarseerPhysics.DebugViewFlags.ContactPoints;
			View.Flags |= FarseerPhysics.DebugViewFlags.PerformanceGraph;
			HideObjects = false;
		}

		public void Initialize() {
            Finished = false;

			// Generate
			if( !Generated ) {
				if( GeneratorTypeName != null && GeneratorTypeName.Length > 0 )
					GeneratorType = Type.GetType( GeneratorTypeName );

				SolarSysGenerator gen = (SolarSysGenerator)Activator.CreateInstance( GeneratorType, this, Seed );
				gen.Generate();
				Generated = true;
			}
		}

		public void PostLoad() {
			if( m_EntitySaveStates == null )
				return;

			foreach(EntitySaveState state in m_EntitySaveStates) {
				Entity ent = (Entity)Activator.CreateInstance( state.EntityType );
				ent.World = this;
				ent.ID = state.EntityID;
				ent.LoadSaveState( state );
			}

			foreach(Entity ent in AddedEntities.Values) {
				ent.PostLoad();
				ent.LoadedSaveState = null;
			}

			ClearLoadCache();
		}

		public void OnPlayerJoin( PlayerController controller ) {
			controller.CurrentSystem = this;
			controller.CurrentSystemID = this.ID;

			if( controller.SavedShipState != null ) {
				// Create from saved state
				Ship ship = (Ship)Activator.CreateInstance( controller.SavedShipState.EntityType );
				ship.World = this;
				ship.ID = GetNextID();
				ship.LoadSaveState( controller.SavedShipState );

				ship.PostLoad();
				ship.LoadedSaveState = null;

				controller.Possess( ship );
			} else {
				// New ship
				controller.Possess( (Ship)Activator.CreateInstance(controller.CurrentShipType,this) );

				float angle = Globals.Random;
				controller.CurrentShip.Position = new Vector2(
					(float)Math.Cos( angle ) * 40,
					(float)Math.Sin( angle ) * 40
				);
			}
		}

		public void OnPlayerLeave( PlayerController controller ) {
			if( controller.CurrentShip != null ) {
				controller.CurrentShip.Remove();
				controller.CurrentShip = null; // Explicitly setting this to null will save the ship data
				controller.CurrentSystem = null;
			}
		}

		public void Shutdown() {
		}
		  
		public void Resumed() {
            Finished = false;
		}

		public void Paused() {
		}

		public void Update() {
			// DO NOT USE THIS!
			// The GalaxySession will now handle when to call the solar system updates
		}

		public void InternalUpdate() {
			#if XBOX360
			if( Guide.IsVisible || Instance == null || Globals.CurrentActivity != this )
				return;
			#else
			if( Instance == null || Globals.CurrentActivity != this )
				return;
			#endif

			// Add new entities
			foreach(KeyValuePair<Guid,Entity> kv in AddedEntities)
				Entities.Add( kv.Key, kv.Value );
			AddedEntities.Clear();

			// Add new drawables
			foreach(Drawable d in AddedDrawables)
				Drawables.Add( d );
			AddedDrawables.Clear();
			
			// Remove dead entities
			foreach(KeyValuePair<Guid,Entity> kv in RemovedEntities) {
				if( kv.Value.IsMarkedForRemoval ) {
					kv.Value.OnRemove();
					Entities.Remove( kv.Key );
				}
			}
			RemovedEntities.Clear();

			// Remove dead drawables
			foreach(Drawable d in RemovedDrawables) {
				if( d.IsMarkedForRemoval ) {
					d.OnRemove();
					Drawables.Remove( d );
				}
			}
			RemovedDrawables.Clear();

			if( (Input.IsKeyDown(Keys.RightShift) && !Input.WasKeyDown(Keys.RightShift)) ||
				(Input.IsGamePadButtonDown(GamePadButton.Y) && !Input.WasGamePadButtonDown(GamePadButton.Y)) ) {
				HideObjects = !HideObjects;
			}

			if( Input.IsKeyDown(Keys.OemPlus) || Input.IsGamePadButtonDown(GamePadButton.RightBumper) )
				Surface.ZoomScale = Math.Max( 0.25f, Surface.ZoomScale - 0.25f*Globals.DrawDeltaTime );
			if( Input.IsKeyDown(Keys.OemMinus) || Input.IsGamePadButtonDown(GamePadButton.LeftBumper) )
				Surface.ZoomScale = Math.Min( 1.75f, Surface.ZoomScale + 0.25f*Globals.DrawDeltaTime );

            if ((Input.IsKeyDown(Keys.Enter) && !Input.WasKeyDown(Keys.Enter)) ||
                (Input.IsGamePadButtonDown(GamePadButton.Start) && !Input.WasGamePadButtonDown(GamePadButton.Start)))
            {
                if (Globals.LocalPlayer.CurrentShip.DockedPlanet != null)
                {
                    PlanetMenu planetUI = new PlanetMenu(Globals.LocalPlayer.CurrentShip.DockedPlanet);
                    Globals.PushActivity(planetUI);
                }
                else
                {
                    //Start Pause menu
                    PauseMenu pause = new PauseMenu();
                    Globals.PushActivity(pause);
                }
            }

			// Simulate Physics
			Instance.Step( Globals.UpdateDeltaTime );
			
			// Update all entities
			foreach(KeyValuePair<Guid,Entity> kv in Entities)
				kv.Value.Update();
			
			// Update all drawables
			foreach(Drawable d in Drawables)
				d.Update();

			if( Globals.CurrentActivity == this && ((Input.IsKeyDown(Keys.Escape) && !Input.WasKeyDown(Keys.Escape)) ||
				(Input.IsGamePadButtonDown(GamePadButton.Back) && !Input.WasGamePadButtonDown(GamePadButton.Back))) ) {
				OnPlayerLeave( Globals.LocalPlayer );
				Finished = true;
			}
		}

		public void DrawWorld() {
			// Debug
			if( HideObjects ) {
				Matrix proj = Surface.WorldMatrix * Surface.ViewMatrix * Surface.ProjectionMatrix;
				View.RenderDebugData( ref proj );
			}

			if( !HideObjects ) {
				Ship ship = Globals.LocalPlayer.CurrentShip;
				Vector2 offset = ship.Position * 0.1f;

				Surface.DrawRect( Backdrop, ship.Position-offset, new Vector2(Backdrop.Width,Backdrop.Height)/(Surface.ZoomScale), Vector2.Zero, 0f, Layer.LAYER_20 );
				Surface.DrawRect( Backdrop, ship.Position-offset, new Vector2(Backdrop.Width,Backdrop.Height)/(Surface.ZoomScale), new Vector2(Surface.Width,0), 0f, Layer.LAYER_20 );
				Surface.DrawRect( Backdrop, ship.Position-offset, new Vector2(Backdrop.Width,Backdrop.Height)/(Surface.ZoomScale), new Vector2(Surface.Width,Surface.Height), 0f, Layer.LAYER_20 );
				Surface.DrawRect( Backdrop, ship.Position-offset, new Vector2(Backdrop.Width,Backdrop.Height)/(Surface.ZoomScale), new Vector2(0,Surface.Height), 0f, Layer.LAYER_20 );

				// Draw all entities
				foreach(Entity e in Entities.Values) {
					if( e is Planet && !(e is Sun) ) {
						Surface.DrawColor = Color.White;
						Surface.DrawCircle( Vector2.Zero, e.Position.Length(), 200, 3f, Layer.LAYER_19 );
					}
					e.Draw();
				}
			
				// Draw all drawables
				foreach(Drawable d in Drawables)
					d.Draw();
			}
		}

		public void DrawOverlay() {
            DrawHUD();
        }

		public bool IsModal() {
			return false;
		}

		public bool IsTransparent() {
			return false;
		}

		public bool IsFinished() {
			return Finished;
		}

		// ----------

		public HashSet<Entity> FindObjects( float x, float y, float w, float h ) {
			AABB span = new AABB( new Vector2(x,y), w, h );
			HashSet<Entity> entities = new HashSet<Entity>();

			Instance.QueryAABB(
				fixture => {
					if( fixture.Body.UserData != null && fixture.Body.UserData is Entity && fixture.Body.UserData != this && !entities.Contains((Entity)fixture.Body.UserData) )
						entities.Add( (Entity)fixture.Body.UserData );
					return true;
				},
				ref span
			);

			return entities;
		}
		
		public HashSet<Entity> FindObjects( float x, float y, float radius ) { return FindObjects(new Vector2(x,y),radius); }
		public HashSet<Entity> FindObjects( Vector2 pos, float radius ) {
			AABB span = new AABB( new Vector2(pos.X-radius,pos.Y-radius), radius*2, radius*2 );
			HashSet<Entity> entities = new HashSet<Entity>();

			float radius_radius = radius * radius;

			Instance.QueryAABB(
				fixture => {
					if( fixture.Body.UserData != null && fixture.Body.UserData is Entity && fixture.Body.UserData != this && !entities.Contains((Entity)fixture.Body.UserData) ) {
						Entity ent = (Entity)fixture.Body.UserData;
						if( (ent.Position-pos).LengthSquared() <= radius_radius )
							entities.Add( ent );
					}
					return true;
				},
				ref span
			);

			return entities;
		}

		public void Clear() {
			if( Instance == null )
				return;

			Instance.Clear();
			Instance.ClearForces();
		}

		// ----------

        private void DrawHUD()
        {

            //draws the HUD
            //----------------

			Ship ship = Globals.LocalPlayer.CurrentShip;

            Vector2 FuelDimensions = new Vector2((Surface.Height / Surface.Width) * Fuel.Width,(Surface.Height / Surface.Width) * Fuel.Height);
            Vector2 ItemMenuDimensions = new Vector2((Surface.Height / Surface.Width) * ItemsMenu.Width, (Surface.Height / Surface.Width) * ItemsMenu.Height);
            Vector2 MiniMapDimensions = new Vector2((Surface.Height / Surface.Width) * MiniMap.Width, (Surface.Height / Surface.Width) * MiniMap.Height);
            float SingleItemWindowWidth = (Surface.Width - MiniMapDimensions.X - FuelDimensions.Y) / 7f;

            Vector2 MinimapStart = new Vector2(Surface.Width - MiniMapDimensions.X, Surface.Height - MiniMapDimensions.Y);

            Surface.DrawColor = Color.White;
            Surface.DrawRect(MiniMap, MinimapStart, MiniMapDimensions, Vector2.Zero, 0f, Layer.LAYER_1);
            Surface.DrawRect(Fuel, new Vector2(0, Surface.Height - FuelDimensions.Y), new Vector2(FuelDimensions.X, FuelDimensions.Y), Vector2.Zero, 0f, Layer.LAYER_1);
            Surface.DrawRect(ItemsMenu, new Vector2(0 + FuelDimensions.X, Surface.Height - ItemMenuDimensions.Y), new Vector2(Surface.Width - MiniMapDimensions.X - FuelDimensions.X, ItemMenuDimensions.Y), Vector2.Zero, 0f, Layer.LAYER_1);
			
            DrawMinimap(MinimapStart, MiniMapDimensions);

            //Draws the items in the players' inventory
            foreach (Item item in ship.Inventory)
            {
                int i = 0;

                Vector2 ItemDisplayPos = new Vector2(FuelDimensions.X + SingleItemWindowWidth * i, Surface.Height - ItemMenuDimensions.Y);
                Vector2 ItemDisplaySize = new Vector2(SingleItemWindowWidth, ItemMenuDimensions.Y);
                item.DrawItemCard(ItemDisplayPos, ItemDisplaySize);

                i++;
            }

            //Draws the players' Shield
			Shield shield = Globals.LocalPlayer.CurrentShip.FindInventoryItem<Shield>();
            Surface.DrawColor = Color.Blue;
            if( shield != null ) {
                Surface.DrawRect(new Vector2(0 + FuelDimensions.X, Surface.Height - ItemMenuDimensions.Y - 10f), new Vector2((Surface.Width - MiniMapDimensions.X - FuelDimensions.X) * (shield.ShieldAmount / shield.ShieldMax), 7f), new Vector2(0f, 0.5f), 0f);
			}

            //Draws the players' Health
            Surface.DrawColor = Color.Red;
            if (ship.Health > 0)
                Surface.DrawRect(new Vector2(FuelDimensions.X, Surface.Height - ItemMenuDimensions.Y - 3f), new Vector2((Surface.Width - MiniMapDimensions.X - FuelDimensions.X) * (ship.Health / ship.MaxHealth), 7f), new Vector2(0f, 0.5f), 0f);

            //Illustrates how much fuel is left
            Surface.DrawColor = Color.Brown;
            if (ship.Fuel > 0)
                Surface.DrawRect(new Vector2(5, Surface.Height - 3 - ((FuelDimensions.Y / 2) * ((float)ship.Fuel / (float)ship.MaxFuel))), new Vector2(FuelDimensions.X - 10, (FuelDimensions.Y - 13) * ((float)(ship.Fuel) / (float)(ship.MaxFuel))), new Vector2(0f, 0.5f), 0f, Layer.LAYER_1-Layer.SUBLAYER_1);

            //Shows Numeral Value about how much fuel is left
            Surface.DrawColor = Color.CornflowerBlue;
            if (ship.Fuel == ship.MaxFuel)
            {
                Surface.DrawString("Default", "FULL", new Vector2(10, Surface.Height - 30), Vector2.Zero, 0f, Layer.LAYER_1-Layer.SUBLAYER_2);
            }
            else if (ship.Fuel > 0)
                Surface.DrawString("Default", ((int)ship.Fuel).ToString(), new Vector2(10, Surface.Height - 30), Vector2.Zero, 0f, Layer.LAYER_1-Layer.SUBLAYER_2);

            //------Done drawing the HUD---------

            // Debug
			Surface.DrawColor = Color.White;
            Surface.DrawString("Default", "Zoom: " + Surface.ZoomScale, new Vector2(5f,0f), Vector2.Zero, 0f);
        }

        private void DrawMinimap(Vector2 start, Vector2 size)
        {

            //start.X += (size.X * (24f / 304f));
            //start.Y += (size.Y * (25f / 252f));
            //size.X *= (269f / 304f);
            //size.Y *= (211f / 252f);

            BoundingBox MinimapCollisionBox1 = new BoundingBox(Vector3.Zero, new Vector3(Surface.Width, start.Y, 0));
            BoundingBox MinimapCollisionBox2 = new BoundingBox(Vector3.Zero, new Vector3(start.X, Surface.Height, 0));

            Vector2 maxDistance = Vector2.Zero;
            List<Planet> MinimapPlanets = new List<Planet>();
            List<Ship> MinimapShips = new List<Ship>();
            List<Enemy> MinimapEnemies = new List<Enemy>();
            foreach(Entity ent in Entities.Values)
            {
                if (ent is Planet)
                {
                    MinimapPlanets.Add((Planet)ent);
                    float curX = Math.Abs(ent.Position.X) + ((Planet)ent).Radius;
                    float curY = Math.Abs(ent.Position.Y) + ((Planet)ent).Radius;
                    if (curX > maxDistance.X)
                    {
                        maxDistance.X = curX;
                    }
                    if (curY > maxDistance.Y)
                    {
                        maxDistance.Y = curY;
                    }
                }
                else if (ent is Ship)
                {
                    MinimapShips.Add((Ship)ent);
                }
                else if (ent is Enemy)
                {
                    MinimapEnemies.Add((Enemy)ent);
                }
            }

            if (maxDistance.X > maxDistance.Y)
                maxDistance.Y = maxDistance.X;
            else
                maxDistance.X = maxDistance.Y;


            size = size / 2f;
            start = start + size + new Vector2( 5, 0 );
            Vector2 minimapScalar = size / maxDistance;
            minimapScalar.Y *= -1;

            foreach (Planet planets in MinimapPlanets)
            {
				Vector2 offset = minimapScalar * planets.Position * .7f;

				//Surface.DrawColor = Color.Yellow * 0.5f;
				//Surface.DrawCircle( start, offset.Length() - 1, 20, 0.5f );

				Surface.DrawColor = Color.Yellow;
                Surface.DrawRect(Circle, start + offset, planets.Radius * new Vector2(minimapScalar.Y,minimapScalar.Y), Vector2.Zero, 0f);
            }

            Surface.DrawColor = Color.CornflowerBlue;
            foreach (Ship ships in MinimapShips)
            {
                BoundingSphere ShipLocation = new BoundingSphere(new Vector3(start + minimapScalar * ships.Position * .7f, 0), ((ships.Sprite.Size.X * minimapScalar.X) * 0.05f * ships.DrawScale.X));
                if (!ShipLocation.Intersects(MinimapCollisionBox1) && !ShipLocation.Intersects(MinimapCollisionBox2))
                    Surface.DrawRect(Circle, start + minimapScalar * ships.Position * .7f, ships.Sprite.Size * new Vector2(minimapScalar.X, minimapScalar.Y) * 0.05f * ships.DrawScale, Vector2.Zero, 0f);
            }

            Surface.DrawColor = Color.Red;
            foreach (Enemy enemies in MinimapEnemies)
            {
                BoundingSphere EnemyLocation = new BoundingSphere(new Vector3(start + minimapScalar * enemies.Position * .7f, 0), (enemies.Sprite.Size.X * minimapScalar.X) * 0.05f * enemies.DrawScale.X);
                if (!EnemyLocation.Intersects(MinimapCollisionBox1) && !EnemyLocation.Intersects(MinimapCollisionBox2))
                    Surface.DrawRect(Circle, start + minimapScalar * enemies.Position * .7f, enemies.Sprite.Size * new Vector2(minimapScalar.X, minimapScalar.Y) * 0.05f * enemies.DrawScale, Vector2.Zero, 0f);
            }
        }

		public Guid GetNextID() {
			Guid ret;
			do {
				byte[] seed = BitConverter.GetBytes( this.Seed );
				ret = new Guid(
					this.Galaxy.Seed,
					BitConverter.ToInt16(seed,0),
					BitConverter.ToInt16(seed,2),
					BitConverter.GetBytes( this.NextAvailableEntID )
				);
				this.NextAvailableEntID++;
			} while( this.AddedEntities.ContainsKey(ret) || this.Entities.ContainsKey(ret) );
			return ret;
		}

		// ----------

        private Texture2D Backdrop { get; set; }
        private Texture2D ItemsMenu { get; set; }
        private Texture2D MiniMap { get; set; }
        private Texture2D Fuel { get; set; }
        private Texture2D Circle { get; set; }

		[XmlIgnore]public FarseerPhysics.Dynamics.World Instance { get; private set; }
		[XmlIgnore]public bool Finished { get; set; }

		[XmlIgnore]public HashSet<Drawable> Drawables { get; private set; }
		[XmlIgnore]public HashSet<Drawable> AddedDrawables { get; private set; }
		[XmlIgnore]public HashSet<Drawable> RemovedDrawables { get; private set; }

		[XmlIgnore]public Dictionary<Guid,Entity> Entities { get; private set; }
		[XmlIgnore]public Dictionary<Guid,Entity> AddedEntities { get; private set; }
		[XmlIgnore]public Dictionary<Guid,Entity> RemovedEntities { get; private set; }
		[XmlIgnore]public long NextAvailableEntID { get; set; }
		
		[XmlIgnore]public Galaxy Galaxy { get; set; }
		[XmlIgnore]public Tree<SolarSys> GalaxyNode { get; set; }
		
        public int Seed { get; set; }
		[XmlIgnore]public Type GeneratorType { get; set; }
		public string GeneratorTypeName { get; set; }
		public bool Generated { get; set; }

		public Vector2 Position { get; set; }
        public int AbundantMineral { get; set; }

		public Guid ID {
			get {
				byte[] seed = BitConverter.GetBytes( Seed );
				return new Guid(
					Galaxy.Seed,
					BitConverter.ToInt16(seed,0),
					BitConverter.ToInt16(seed,2),
					new byte[8]
				);
			}
		}

		// Saving and loading
		// This is only existant during a load which is why it generates and does not save
		private Guid[] m_GalaxyNeighboringGuids;
		public Guid[] GalaxyNeighboringGuids {
			get {
				if( m_GalaxyNeighboringGuids != null )
					return m_GalaxyNeighboringGuids;

				Guid[] guids = new Guid[GalaxyNode.Children.Count];
				int i = 0;

				foreach(Tree<SolarSys> child in GalaxyNode.Children) {
					guids[i] = child.Data.ID;
					i++;
				}

				return guids;
			}
			set {
				m_GalaxyNeighboringGuids = value;
			}
		}
		
		private EntitySaveState[] m_EntitySaveStates;
		public EntitySaveState[] EntitySaveStates {
			get {
				if( m_EntitySaveStates != null )
					return m_EntitySaveStates;

				if( !Generated )
					return null;

				List<EntitySaveState> states = new List<EntitySaveState>();

				foreach(Entity ent in AddedEntities.Values) {
					if( ent.IsMarkedForRemoval )
						continue;
					EntitySaveState state = new EntitySaveState( ent );
					states.Add( state );
				}

				foreach(Entity ent in Entities.Values) {
					if( ent.IsMarkedForRemoval )
						continue;
					EntitySaveState state = new EntitySaveState( ent );
					states.Add( state );
				}

				return states.ToArray();
			}
			set {
				m_EntitySaveStates = value;
			}
		}

		public void ClearLoadCache() { m_GalaxyNeighboringGuids = null; m_EntitySaveStates = null; }

		private FarseerPhysics.DebugViews.DebugViewXNA View;
		private bool HideObjects { get; set; }
	}
}
